﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Data.SqlClient;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Net;
using System.Net.Mail;

namespace DongBoDuLieu
{
    public enum ChangeType
    {
        None = 0, Insert = 1, Update = 2, Delete = 3
    }

    public partial class DongBoDuLieu : ServiceBase
    {
        //System.Timers.Timer timer = new System.Timers.Timer();

        public DongBoDuLieu()
        {
            InitializeComponent();
        }

        //Một số server parameter
        //Server Name   SMTP Address	        Port	SSL
        //Yahoo!	    smtp.mail.yahoo.com	    587	    Yes
        //GMail	        smtp.gmail.com	        587	    Yes
        //Hotmail	    smtp.live.com	        587	    Yes

        string smtpAddress = "smtp.gmail.com";
        int portNumber = 587;
        bool enableSSL = true;

        string emailFrom = "hattieuit88@gmail.com";
        string password = "hoabattu";
        string emailTo = "vqphuong88@gmail.com";
        string subject = "";
        string body = "";

        private void ReadFileSettingsToLocalSettings()
        {
            int counter = 1;
            string[] line = new string[20]; //Đọc được 20 dòng

            // Read the file and display it line by line.
            System.IO.StreamReader file =
               new System.IO.StreamReader("c:\\SynSettings.txt");
            while ((line[counter] = file.ReadLine()) != null)
            {
                counter++;
            }
            LocalSettings.HeThong.DB_Server = line[1];
            LocalSettings.HeThong.DB_UID = line[2];
            LocalSettings.HeThong.DB_PASS = line[3];
            LocalSettings.HeThong.DB_Name = line[4];

            LocalSettings.HeThong.DB_Server2 = line[5];
            LocalSettings.HeThong.DB_UID2 = line[6];
            LocalSettings.HeThong.DB_PASS2 = line[7];
            LocalSettings.HeThong.DB_Name2 = line[8];

            LocalSettings.HeThong.StoreName1 = line[9];
            LocalSettings.HeThong.StoreName2 = line[10];

            LocalSettings.HeThong.ChuKyTuDongDongBo = Convert.ToInt32(line[11]);
            LocalSettings.HeThong.ChieuDongBo = (ChieuDongBo)Convert.ToInt32(line[12]);
            LocalSettings.HeThong.KieuDongBo = (KieuDongBo)Convert.ToInt32(line[13]);

            file.Close();
        }

        private System.Threading.Timer _timer;
        protected override void OnStart(string[] args)
        {
            System.Diagnostics.Debugger.Launch();
            try
            {
                if (LocalSettings.HeThong == null)
                {
                    LocalSettings.HeThong = new LocalSettings();
                }

                ReadFileSettingsToLocalSettings();
                Use_Notify();

                SynData();

                TimerCallback callback = new TimerCallback(OnTimedEvent);
                _timer = new System.Threading.Timer(callback, null, 60000, 60000);
            }
            catch (Exception ex)
            {
            }
        }

        private void OnTimedEvent(Object stateInfo)
        {
            Console.WriteLine("da tich:" + DateTime.Now);

            TimeSpan duration = DateTime.Now - LocalSettings.HeThong.LastUpdate;

            try
            {
                if (duration.TotalMinutes >= LocalSettings.HeThong.ChuKyTuDongDongBo)
                {
                    LocalSettings.HeThong.LastUpdate = DateTime.Now;

                    _timer.Change(60000, 60000 * 3600);//Như là Stop đồng hồ lại 1h sau mới gọi callback (tick) tiếp
                    SynData();
                    _timer.Change(60000, 60000 * LocalSettings.HeThong.ChuKyTuDongDongBo);//Như là Start đồng hồ lại 1h sau mới gọi callback (tick) tiếp
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Không chạy tự đồng bộ theo chu kì được.\n Lỗi: " + ex.Message);
            }
        }

        protected override void OnStop()
        {
            _timer.Dispose();
            this.notifyIcon.Dispose();
        }

        SqlDataAdapter _DataAdapter = new SqlDataAdapter();
        DataTable _DataTableSynInfo1 = new DataTable();
        DataTable _DataTableSynInfo2 = new DataTable();
        string _ErrorMessage = "";
        string _CaptionInShowErrorMessage = "Lỗi đồng bộ";
        #region ConnectionString1
        public string ConnectionString1
        {
            get
            {
                return string.Format("SERVER = {0}; DATABASE = {1}; UID= {2}; PWD={3}",
                LocalSettings.HeThong.DB_Server, LocalSettings.HeThong.DB_Name, LocalSettings.HeThong.DB_UID, LocalSettings.HeThong.DB_PASS);
            }
        }
        #endregion
        #region ConnectionString2
        public string ConnectionString2
        {
            get
            {
                return string.Format("SERVER = {0}; DATABASE = {1}; UID= {2}; PWD={3}",
                LocalSettings.HeThong.DB_Server2, LocalSettings.HeThong.DB_Name2, LocalSettings.HeThong.DB_UID2, LocalSettings.HeThong.DB_PASS2);
            }
        }

        #endregion
        public string TenCuaHang1
        {
            get
            {
                return LocalSettings.HeThong.StoreName1.Trim();
            }
        }
        public string TenCuaHang2
        {
            get
            {
                return LocalSettings.HeThong.StoreName2.Trim();
            }
        }
        string _BangCanUuTien = "'VatTuHangHoa', 'NhomVatTuHangHoa', 'DoiTuongNghiepVu'";

        private bool CheckConnectServer(string connectionString, bool isTrungTam)
        {
            //FrmProgressBar.StartShowProgress("Kiểm tra kết nối");
            using (SqlConnection con = new SqlConnection())
            {
                con.ConnectionString = connectionString;
                try
                {
                    con.Open();
                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
                finally
                {
                    //FrmProgressBar.FinishShowProgress();
                    if (con.State == ConnectionState.Open) con.Close();
                }
            }
        }       //Kiểm tra kết nối đến server
        private void Use_Notify()
        {
            LocalSettings.HeThong.TuDongDongBo = true;

            notifyIcon.ContextMenuStrip = contextMenuStrip;
            notifyIcon.BalloonTipText = "Đồng bộ CSDL giữa các cửa hàng.";
            notifyIcon.BalloonTipTitle = "Chương trình đồng bộ";
            notifyIcon.ShowBalloonTip(1);
        }        //Hiển thị Notify nếu để ở chế độ minimaze

        private void LoadSyninfoToMemory()
        {
            SqlConnection con1 = new SqlConnection(), con2 = new SqlConnection();
            con1.ConnectionString = ConnectionString1;
            con2.ConnectionString = ConnectionString2;
            try
            {
                con1.Open();
                con2.Open();
                SqlCommand cmd1 = con1.CreateCommand();
                SqlCommand cmd2 = con2.CreateCommand();

                cmd1.CommandText = string.Format("SELECT * FROM SynInfo WHERE TableName IN ({0}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{1}')  \n" +
                                                 "UNION \n" +
                                                 "SELECT * FROM SynInfo WHERE TableName NOT IN ({0}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{1}') ",
                                                 _BangCanUuTien, TenCuaHang2);
                _DataAdapter.SelectCommand = cmd1;
                _DataTableSynInfo1.Clear();
                _DataAdapter.Fill(_DataTableSynInfo1);

                cmd2.CommandText = string.Format("SELECT * FROM SynInfo WHERE TableName IN ({0}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{1}') \n" +
                                                 "UNION \n" +
                                                 "SELECT * FROM SynInfo WHERE TableName NOT IN ({0}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{1}') ",
                                                 _BangCanUuTien, TenCuaHang1);
                _DataAdapter.SelectCommand = cmd2;
                _DataTableSynInfo2.Clear();
                _DataAdapter.Fill(_DataTableSynInfo2);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi khi load dữ liệu bảng SynInfo" + ex.Message);
            }
        }       //Load SynInfo lên bộ nhớ để xử lý, có thể dùng để load lại khi cần
        private void LoadSyninfoToMemory(int numberOfRowInBlockSyn)
        {
            SqlConnection con1 = new SqlConnection(), con2 = new SqlConnection();
            con1.ConnectionString = ConnectionString1;
            con2.ConnectionString = ConnectionString2;
            try
            {
                con1.Open();
                con2.Open();
                SqlCommand cmd1 = con1.CreateCommand();
                SqlCommand cmd2 = con2.CreateCommand();

                cmd1.CommandText = string.Format("SELECT TOP {0} * FROM SynInfo WHERE TableName IN ({1}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{2}')  \n" +
                                                 "UNION \n" +
                                                 "SELECT TOP {0} * FROM SynInfo WHERE TableName NOT IN ({1}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{2}') ",
                                                 numberOfRowInBlockSyn, _BangCanUuTien, TenCuaHang2);
                _DataAdapter.SelectCommand = cmd1;
                _DataTableSynInfo1.Clear();
                _DataAdapter.Fill(_DataTableSynInfo1);

                cmd2.CommandText = string.Format("SELECT TOP {0} * FROM SynInfo WHERE TableName IN ({1}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{2}') \n" +
                                                 "UNION \n" +
                                                 "SELECT TOP {0} * FROM SynInfo WHERE TableName NOT IN ({1}) AND StoreID IN (SELECT StoreID FROM Store WHERE Name = '{2}') ",
                                                 numberOfRowInBlockSyn, _BangCanUuTien, TenCuaHang1);
                _DataAdapter.SelectCommand = cmd2;
                _DataTableSynInfo2.Clear();
                _DataAdapter.Fill(_DataTableSynInfo2);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi khi load dữ liệu bảng SynInfo" + ex.Message);
            }
        }       //Load SynInfo lên bộ nhớ để xử lý, có thể dùng để load lại khi cần

        private void ShowMessageAutoClose(string message, string caption, uint timerStopShowMessage, bool fromSynProcess, bool sendEmail)
        {
            try
            {
                notifyIcon.BalloonTipText = message;
                notifyIcon.BalloonTipTitle = caption;
                notifyIcon.ShowBalloonTip(1);

                if (sendEmail) SendEmail(message, caption);
                //Viết log vào ổ C:
                ErrorLogging(message);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi method hiện thông báo: " + ex.Message);
            }
        }
        private void ShowMessageAutoClose(string message, string caption, uint timerStopShowMessage, bool fromSynProcess, bool sendEmail, string sql1, string sql2)
        {
            try
            {
                notifyIcon.BalloonTipText = message;
                notifyIcon.BalloonTipTitle = caption;
                notifyIcon.ShowBalloonTip(1);

                if (sendEmail) SendEmail(message, caption, sql1, sql2);

                //Viết log vào ổ C:
                ErrorLogging(message);

            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi method hiện thông báo: " + ex.Message);
            }
        }
        private void SendEmail(string error, string caption)
        {
            try
            {
                //TimeSpan span = DateTime.Now - LocalSettings.HeThong.LastSendEmail;

                //if (Math.Abs(span.Minutes) >= 30)  //30 phút gửi 1 email, không gmail cho vào spam 
                //{
                //    subject = TenCuaHang1 + " đến " + TenCuaHang2 + " - " + CommonLib.DateTimeVNToString(DateTime.Now);
                //    body = string.Format("Caption: {0}.     Error: {1}", caption, error);

                //    using (MailMessage mail = new MailMessage())
                //    {
                //        mail.From = new MailAddress(emailFrom);
                //        mail.To.Add(emailTo);
                //        mail.Subject = subject;
                //        mail.Body = body;
                //        mail.IsBodyHtml = true;
                //        // Can set to false, if you are sending pure text.

                //        //mail.Attachments.Add(new Attachment("C:\\SomeFile.txt"));
                //        //mail.Attachments.Add(new Attachment("C:\\SomeZip.zip"));

                //        SmtpClient smtp = new SmtpClient(smtpAddress, portNumber);
                //        smtp.Credentials = new NetworkCredential(emailFrom, password);
                //        smtp.EnableSsl = enableSSL;
                //        smtp.Send(mail);
                //        LocalSettings.HeThong.LastSendEmail = DateTime.Now;
                //    }
                //}
            }
            catch (Exception ex)
            {
            }
        }
        private void SendEmail(string error, string caption, string sql1, string sql2)
        {
            try
            {
                //TimeSpan span = DateTime.Now - LocalSettings.HeThong.LastSendEmail;

                //if (Math.Abs(span.Minutes) >= 30)  //30 phút gửi 1 email, không gmail cho vào spam 
                //{
                //    subject = TenCuaHang1 + " đến " + TenCuaHang2 + " - " + CommonLib.DateTimeVNToString(DateTime.Now); ;
                //    body = string.Format("Caption: {0}.     Error: {1}.     Sql1 (by cmd1): {2}.        Sql2 (by cmd2): {3}",
                //        caption, error, sql1, sql2);

                //    using (MailMessage mail = new MailMessage())
                //    {
                //        mail.From = new MailAddress(emailFrom);
                //        mail.To.Add(emailTo);
                //        mail.Subject = subject;
                //        mail.Body = body;
                //        mail.IsBodyHtml = true;
                //        // Can set to false, if you are sending pure text.

                //        //mail.Attachments.Add(new Attachment("C:\\SomeFile.txt"));
                //        //mail.Attachments.Add(new Attachment("C:\\SomeZip.zip"));

                //        SmtpClient smtp = new SmtpClient(smtpAddress, portNumber);
                //        smtp.Credentials = new NetworkCredential(emailFrom, password);
                //        smtp.EnableSsl = enableSSL;
                //        smtp.Send(mail);
                //        LocalSettings.HeThong.LastSendEmail = DateTime.Now;
                //    }
                //}
            }
            catch (Exception ex)
            {
            }
        }
        public static void ErrorLogging(Exception ex)
        {
            string strPath = @"C:\LoiDongBo.txt";
            if (!File.Exists(strPath))
            {
                File.Create(strPath).Dispose();
            }
            using (StreamWriter sw = File.AppendText(strPath))
            {
                sw.WriteLine("=============Error Logging ===========");
                sw.WriteLine("===========Start============= " + DateTime.Now);
                sw.WriteLine("Error Message: " + ex.Message);
                sw.WriteLine("Stack Trace: " + ex.StackTrace);
                sw.WriteLine("===========End============= " + DateTime.Now);

            }
        }
        public static void ErrorLogging(string ex)
        {
            string strPath = @"C:\LoiDongBo.txt";
            if (!File.Exists(strPath))
            {
                File.Create(strPath).Dispose();
            }
            using (StreamWriter sw = File.AppendText(strPath))
            {
                sw.WriteLine("=============Error Logging ===========");
                sw.WriteLine("===========Start============= " + DateTime.Now);
                sw.WriteLine("Error Message: " + ex);
                sw.WriteLine("===========End============= " + DateTime.Now);

            }
        }

        private void NormalLifeConflictMaHang()
        {
            //Truyền connection vào không dùng được Transaction nên phải khởi tạo connnection mới trong method này
            SqlConnection conI = new SqlConnection(), conII = new SqlConnection();
            conI.ConnectionString = ConnectionString1;
            conII.ConnectionString = ConnectionString2;
            SqlCommand cmd1 = conI.CreateCommand();
            SqlCommand cmd2 = conII.CreateCommand();

            string storeID = "";
            string tableName = "";
            string tableID = "";
            string recordID = "";
            ChangeType changeType = ChangeType.None;

            DataRow[] rows1 = _DataTableSynInfo1.Select("TableName = 'VatTuHangHoa'");
            DataRow[] rows2 = _DataTableSynInfo2.Select("TableName = 'VatTuHangHoa'");
            try
            {
                conI.Open();
                conII.Open();

                /*Tất cả đều được chuẩn hóa theo CSDL Trung tâm*/
                #region Check các trường hợp gây xung đột dữ liệu từ Trung tâm xuống Trạm từ bảng VatTuHangHoa do Mã và ID gây ra
                foreach (DataRow row in rows1)
                {
                    try
                    {
                        storeID = row[1].ToString();
                        tableName = row[2].ToString();
                        tableID = tableName + "ID";
                        recordID = row[3].ToString();
                        changeType = (ChangeType)(Convert.ToInt32(row[4].ToString()));

                        try
                        {
                            SqlDataAdapter dataAdapterCheck = new SqlDataAdapter();
                            DataTable dataTableCheck = new DataTable();

                            //neu kieu changeType = update va ID nay khong co tren DB tram ==> chuyen thanh Insert
                            //phải check trường hợp này trước Insert vì Insert có nhiều thứ đặc biệt
                            if (changeType == ChangeType.Update)
                            {
                                dataTableCheck.Clear();
                                cmd2.Parameters.Clear();

                                cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                dataAdapterCheck.SelectCommand = cmd2;
                                dataAdapterCheck.Fill(dataTableCheck);
                                if (dataTableCheck.Rows.Count == 0)
                                {
                                    changeType = ChangeType.Insert;
                                }
                            }
                            //neu kieu changeType = insert va ID nay da co tren DB tram
                            if (changeType == ChangeType.Insert)
                            {
                                dataTableCheck.Clear();
                                cmd2.Parameters.Clear();

                                cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                dataAdapterCheck.SelectCommand = cmd2;
                                dataAdapterCheck.Fill(dataTableCheck);

                                if (dataTableCheck.Rows.Count != 0)    // Có ID bên CSDL Trạm rồi
                                {
                                    changeType = ChangeType.Update;
                                }
                                else //Chưa có ID này bên CSDL Trạm trong bảng VatTuHangHoa
                                {
                                    dataTableCheck.Clear();

                                    //Lấy thông tin hàng từ CSDL Trung tâm
                                    cmd1.CommandText = string.Format("SELECT * FROM VatTuHangHoa WHERE ID = '{0}'", recordID);
                                    dataAdapterCheck.SelectCommand = cmd1;
                                    dataAdapterCheck.Fill(dataTableCheck);

                                    string idInTrungTam = dataTableCheck.Rows[0]["ID"].ToString();
                                    string maHangInTrungTam = dataTableCheck.Rows[0]["Ma"].ToString();
                                    string tenHangInTrungTam = dataTableCheck.Rows[0]["Ten"].ToString();

                                    //Xem thông tin hàng có  mã trên trong CSDL Trạm 
                                    dataTableCheck.Clear();

                                    cmd2.CommandText = string.Format("SELECT * FROM VatTuHangHoa WHERE Ma = '{0}'", maHangInTrungTam);
                                    dataAdapterCheck.SelectCommand = cmd2;
                                    dataAdapterCheck.Fill(dataTableCheck);

                                    if (dataTableCheck.Rows.Count != 0) //Tồn tại hàng có mã này rồi nhưng ID 2 bên khác nhau. Ta không thể Insert được mà phải chuẩn hóa lại
                                    {
                                        string idInTram = dataTableCheck.Rows[0]["ID"].ToString();
                                        string maHangInTram = dataTableCheck.Rows[0]["Ma"].ToString();
                                        string tenHangInTram = dataTableCheck.Rows[0]["Ten"].ToString();

                                        SqlTransaction transaction = conII.BeginTransaction();
                                        cmd2.Transaction = transaction;
                                        try
                                        {
                                            //replace ID và tên hàng của CSDL Trạm theo trung tâm dựa vào mã hàng
                                            cmd2.CommandText = string.Format("UPDATE VatTuHangHoa SET ID = '{0}', Ten = '{1}' WHERE Ma = '{2}'", idInTrungTam, tenHangInTrungTam, maHangInTram);
                                            cmd2.ExecuteNonQuery();
                                            cmd2.CommandText = string.Format("UPDATE KhoanMucChungTu SET VatTuHangHoa1ID = '{0}' WHERE VatTuHangHoa1ID = '{1}'", idInTrungTam, idInTram);
                                            cmd2.ExecuteNonQuery();
                                            cmd2.CommandText = string.Format("UPDATE TonKho SET VatTuHangHoaID = '{0}' WHERE VatTuHangHoaID = '{1}'", idInTrungTam, idInTram);
                                            cmd2.ExecuteNonQuery();

                                            //Thay ChangeType thành Update vào bảng SynInfo vào bảng SynInfo
                                            cmd2.CommandText = string.Format("UPDATE SynInfo SET ChangeType = 2 WHERE RecordID = '{0}'", idInTrungTam);
                                            cmd2.ExecuteNonQuery();

                                            transaction.Commit();
                                        }
                                        catch (SqlException sqlEx)
                                        {
                                            throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                                        }
                                        catch (Exception ex)
                                        {
                                            if (ex is CustomException) throw ex;
                                            else
                                            {
                                                throw new CustomException(ex.Message);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        catch (SqlException sqlEx)
                        {
                            throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                        }
                        catch (Exception ex)
                        {
                            if (ex is CustomException) throw ex;
                            else
                            {
                                throw new CustomException(ex.Message);
                            }
                        }
                    }
                    catch (SqlException sqlEx)
                    {
                        throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                    }
                    catch (Exception ex)
                    {
                        if (ex is CustomException) throw ex;
                        else
                        {
                            throw new CustomException(ex.Message);
                        }
                    }
                }
                #endregion

                #region Check các trường hợp gây xung đột dữ liệu từ Trạm lên Trung tâm từ bảng VatTuHangHoa do Mã và ID gây ra
                foreach (DataRow row in rows2)
                {
                    try
                    {
                        storeID = row[1].ToString();
                        tableName = row[2].ToString();
                        tableID = tableName + "ID";
                        recordID = row[3].ToString();

                        changeType = (ChangeType)(Convert.ToInt32(row[4].ToString()));

                        try
                        {
                            SqlDataAdapter dataAdapterCheck = new SqlDataAdapter();
                            DataTable dataTableCheck = new DataTable();

                            //neu kieu changeType = update va ID nay khong co tren DB tram ==> chuyen thanh Insert
                            //phải check trường hợp này trước Insert vì Insert có nhiều thứ đặc biệt
                            if (changeType == ChangeType.Update)
                            {
                                cmd1.Parameters.Clear();

                                cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                dataAdapterCheck.SelectCommand = cmd1;
                                dataAdapterCheck.Fill(dataTableCheck);
                                if (dataTableCheck.Rows.Count == 0)
                                {
                                    changeType = ChangeType.Insert;
                                }
                            }

                            //neu kieu changeType = insert va ID nay _DataAdapter co tren DB tram ==> chuyen thanh Update
                            if (changeType != ChangeType.None)
                            {
                                cmd1.Parameters.Clear();

                                cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                dataAdapterCheck.SelectCommand = cmd1;
                                dataAdapterCheck.Fill(dataTableCheck);

                                if (dataTableCheck.Rows.Count != 0)    // Có ID bên CSDL Trung tâm rồi
                                {
                                    //cmd2.CommandText = string.Format("UPDATE SynInfo SET ChangeType = 2 WHERE RecordID = '{0}'", idInTram);
                                    //cmd2.ExecuteNonQuery();
                                    //cmd2.CommandText = string.Format("UPDATE SynInfo SET RecordID = '{0}' WHERE RecordID = '{1}'", idInTrungTam, idInTram);
                                    //cmd2.ExecuteNonQuery();
                                    changeType = ChangeType.Update;

                                }
                                else //Chưa có ID bên CSDL Trung tâm trong bảng VatTuHangHoa
                                {
                                    cmd1.Parameters.Clear();
                                    cmd2.Parameters.Clear();
                                    dataTableCheck.Clear();

                                    //Lấy mã hàng từ CSDL Trạm, vì trạm phải theo trung tâm, mà trung tâm k có ID trên nên phải thông qua mã từ trạm
                                    cmd2.CommandText = string.Format("SELECT * FROM VatTuHangHoa WHERE ID = '{0}' ", recordID);
                                    dataAdapterCheck.SelectCommand = cmd2;
                                    dataAdapterCheck.Fill(dataTableCheck);
                                    if (dataTableCheck.Rows.Count > 0)
                                    {
                                        string maHangInTram = dataTableCheck.Rows[0]["Ma"].ToString();

                                        //Lấy thông tin từ CSDL Trung tâm
                                        dataTableCheck.Clear();

                                        cmd1.CommandText = string.Format("SELECT * FROM VatTuHangHoa WHERE Ma = '{0}' ", maHangInTram);
                                        dataAdapterCheck.SelectCommand = cmd1;
                                        dataAdapterCheck.Fill(dataTableCheck);

                                        string idInTrungTam = dataTableCheck.Rows[0]["ID"].ToString();
                                        string maHangInTrungTam = dataTableCheck.Rows[0]["Ma"].ToString();
                                        string tenHangInTrungTam = dataTableCheck.Rows[0]["Ten"].ToString();

                                        //Xem thông tin hàng có  mã trên trong CSDL Trạm 
                                        dataTableCheck.Clear();

                                        cmd2.CommandText = string.Format("SELECT * FROM VatTuHangHoa WHERE Ma = '{0}'", maHangInTrungTam);
                                        dataAdapterCheck.SelectCommand = cmd2;
                                        dataAdapterCheck.Fill(dataTableCheck);

                                        if (dataTableCheck.Rows.Count != 0) //Tồn tại hàng có mã này rồi nhưng ID 2 bên khác nhau. Ta không thể Insert được mà phải chuẩn hóa lại
                                        {
                                            string idInTram = dataTableCheck.Rows[0]["ID"].ToString();
                                            maHangInTram = dataTableCheck.Rows[0]["Ma"].ToString();
                                            string tenHangInTram = dataTableCheck.Rows[0]["Ten"].ToString();

                                            SqlTransaction transaction = conII.BeginTransaction();
                                            cmd2.Transaction = transaction;
                                            try
                                            {
                                                //replace ID và tên hàng của CSDL Trạm theo trung tâm dựa vào mã hàng
                                                cmd2.CommandText = string.Format("UPDATE VatTuHangHoa SET ID = '{0}' WHERE Ma = '{1}'", idInTrungTam, maHangInTram);
                                                cmd2.ExecuteNonQuery();
                                                cmd2.CommandText = string.Format("UPDATE KhoanMucChungTu SET VatTuHangHoa1ID = '{0}' WHERE VatTuHangHoa1ID = '{1}'", idInTrungTam, idInTram);
                                                cmd2.ExecuteNonQuery();
                                                cmd2.CommandText = string.Format("UPDATE TonKho SET VatTuHangHoaID = '{0}'  WHERE VatTuHangHoaID = '{1}'", idInTrungTam, idInTram);
                                                cmd2.ExecuteNonQuery();

                                                //Thay recordID mới,ChangeType thành Update vào bảng SynInfo vào bảng SynInfo
                                                cmd2.CommandText = string.Format("UPDATE SynInfo SET ChangeType = 2 WHERE RecordID = '{0}'", idInTram);
                                                cmd2.ExecuteNonQuery();
                                                cmd2.CommandText = string.Format("UPDATE SynInfo SET RecordID = '{0}' WHERE RecordID = '{1}'", idInTrungTam, idInTram);
                                                cmd2.ExecuteNonQuery();

                                                transaction.Commit();
                                            }
                                            catch (SqlException sqlEx)
                                            {
                                                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                                            }
                                            catch (Exception ex)
                                            {
                                                if (ex is CustomException) throw ex;
                                                else
                                                {
                                                    throw new CustomException(ex.Message);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        catch (SqlException sqlEx)
                        {
                            throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                        }
                        catch (Exception ex)
                        {
                            if (ex is CustomException) throw ex;
                            else
                            {
                                throw new CustomException(ex.Message);
                            }
                        }
                    }
                    catch (SqlException sqlEx)
                    {
                        throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                    }
                    catch (Exception ex)
                    {
                        if (ex is CustomException) throw ex;
                        else
                        {
                            throw new CustomException(ex.Message);
                        }
                    }
                }
                #endregion
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new CustomException(ex.Message);
                }
            }
            finally
            {
                conI.Close();
                conII.Close();
            }
        }      //Chuẩn hóa Bảng VatTuHangHoa
        private void DelDataOrphansInSynInfo()
        {
            SqlConnection conI = new SqlConnection(), conII = new SqlConnection();
            conI.ConnectionString = ConnectionString1;
            conII.ConnectionString = ConnectionString2;
            SqlCommand cmd1 = conI.CreateCommand();
            SqlCommand cmd2 = conII.CreateCommand();
            int conChay = -1;
            string tableName = "";
            string tableID = tableName + "ID";
            string recordID = "";

            try
            {
                conI.Open();
                conII.Open();

                //FrmProgressBar.StartShowProgress("Đang xóa những bản ghi cần đồng bộ nhưng dữ liệu không tồn tại ở cả 2 CSDL");
                #region Xóa những trường không tồn tại ở cả 2 CSDL Trạm và Trung tâm (bảng VatTuHangHoa)
                /*  Trường hợp này sinh ra do khi thay đổi 1 record nhưng lại sinh ra 2 record trong bảng SynInfo.
                    Nguyên nhân là do có thêm Trigger TraceTime để xem ngày giờ thay đổi
                    Khi chuẩn hóa thì thì chuẩn được dòng 1 sau đó ID đã bị thay đổi nên dòng 2 mồ côi. Cần xóa những dòng mồ côi này đi
                    Để đấy cũng không đồng bộ được mà ảnh hưởng đến hiển thị báo cáo */

                //Xử lý SynInfo Trung tâm
                conChay = 0;
                while (_DataTableSynInfo1.Rows.Count > conChay)
                {
                    DataRow row = _DataTableSynInfo1.Rows[conChay];
                    conChay++;
                    tableName = row[2].ToString();
                    tableID = tableName + "ID";
                    recordID = row[3].ToString();

                    DataTable dataTableCheck = new DataTable();
                    try
                    {
                        //Query 2 CSDL xem có danh mục hàng giống trong bảng SynInfo không
                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                        {
                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                        }
                        else
                        {
                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                        }
                        _DataAdapter.SelectCommand = cmd1;
                        _DataAdapter.Fill(dataTableCheck);

                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                        {
                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                        }
                        else
                        {
                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                        }
                        _DataAdapter.SelectCommand = cmd2;
                        _DataAdapter.Fill(dataTableCheck);
                        //Không có bản ghi nào trong dataTableCheck thì xóa đi
                        if (dataTableCheck.Rows.Count == 0)
                        {
                            cmd1.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}'", recordID);
                            cmd1.ExecuteNonQuery();
                        }
                    }
                    catch (SqlException sqlEx)
                    {
                        throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                    }
                    catch (Exception ex)
                    {
                        if (ex is CustomException) throw ex;
                        else
                        {
                            _ErrorMessage = string.Format("Lỗi xóa dữ liệu mồ côi tại CSDL Trung tâm: " + ex.Message);
                            throw new CustomException(_ErrorMessage);
                        }
                    }
                }
                //Xử lý SynInfo Trạm
                conChay = 0;
                while (_DataTableSynInfo1.Rows.Count > conChay)
                {
                    DataRow row = _DataTableSynInfo1.Rows[conChay];
                    conChay++;
                    recordID = row[3].ToString();

                    DataTable dataTableCheck = new DataTable();
                    try
                    {
                        //Query 2 CSDL xem có danh mục hàng giống trong bảng SynInfo không
                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                        {
                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                        }
                        else
                        {
                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                        }
                        _DataAdapter.SelectCommand = cmd1;
                        _DataAdapter.Fill(dataTableCheck);

                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                        {
                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                        }
                        else
                        {
                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                        }
                        _DataAdapter.SelectCommand = cmd2;
                        _DataAdapter.Fill(dataTableCheck);
                        //Không có bản ghi nào trong dataTableCheck thì xóa đi
                        if (dataTableCheck.Rows.Count == 0)
                        {
                            cmd2.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}'", recordID);
                            cmd2.ExecuteNonQuery();
                        }
                    }
                    catch (SqlException sqlEx)
                    {
                        throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                    }
                    catch (Exception ex)
                    {
                        if (ex is CustomException) throw ex;
                        else
                        {
                            _ErrorMessage = string.Format("Lỗi xóa dữ liệu mồ côi tại CSDL Trạm: " + ex.Message);
                            throw new CustomException(_ErrorMessage);
                        }
                    }
                }
                #endregion
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new CustomException(ex.Message);
                }
            }
            finally
            {
                //FrmProgressBar.FinishShowProgress();
                conI.Close();
                conII.Close();
            }
        }     //Xóa tat ca dữ liệu mồ côi do chuẩn hóa
        private void GetListOfColumnsForInsert(out string listOfColumns, out string values, SqlCommand cmd, DataTable dtTableSource)
        {
            cmd.Parameters.Clear();
            values = "";
            listOfColumns = "";
            try
            {
                foreach (DataColumn column in dtTableSource.Columns)
                {
                    //if (column.ColumnName != "LastUpdated")
                    if (column.ColumnName != "") //Đồng bộ cả LastUpdated
                    {
                        values = values + "@" + column.ColumnName + ", ";
                        listOfColumns = listOfColumns + "[" + column.ColumnName + "], ";

                        cmd.Parameters.AddWithValue("@" + column.ColumnName, dtTableSource.Rows[0][column.ColumnName]);
                    }
                }
                if (values.EndsWith(", ")) values = values.Substring(0, values.Length - 2);
                if (listOfColumns.EndsWith(", ")) listOfColumns = listOfColumns.Substring(0, listOfColumns.Length - 2);
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new CustomException(ex.Message);
                }
            }
        }
        private void GetListOfColumnsForUpdate(out string updateQuery, SqlCommand cmd, DataTable dtTableSource)
        {
            cmd.Parameters.Clear();
            updateQuery = "";

            try
            {
                foreach (DataColumn column in dtTableSource.Columns)
                {
                    //if ((column.ColumnName != "LastUpdated") && (column.ColumnName != "ID"))
                    if ((column.ColumnName != "") && (column.ColumnName != "ID"))  //Đồng bộ cả LastUpdated
                    {
                        updateQuery = updateQuery + string.Format("[{0}] = @{0}, ", column.ColumnName);
                        cmd.Parameters.AddWithValue(column.ColumnName, dtTableSource.Rows[0][column.ColumnName]);
                    }
                }
                if (updateQuery.EndsWith(", ")) updateQuery = updateQuery.Substring(0, updateQuery.Length - 2);
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new CustomException(ex.Message);
                }
            }
        }

        private void DeleteAndReInsertRecordInTableMultiFieldIsKeys(string tableName, DataTable dtTableSource, string recordID, string storeID,
                                                                    SqlCommand cmd1, SqlCommand cmd2, bool isTrungTamDenTram)
        {
            //Xóa bản ghi có Key trùng nhau đi. Key phải xác định theo từng bảng
            string queryDelete = "";
            try
            {
                switch (tableName)
                {
                    case "TonKho":
                        queryDelete = string.Format("DELETE FROM TonKho WHERE ThoiDiemKhoaSoID = '{0}' AND KhoID = '{1}' AND VatTuHangHoaID = '{2}'",
                                                                 dtTableSource.Rows[0]["ThoiDiemKhoaSoID"], dtTableSource.Rows[0]["KhoID"], dtTableSource.Rows[0]["VatTuHangHoaID"]);
                        break;
                    case "SoDuTaiKhoan":
                        queryDelete = string.Format("DELETE FROM SoDuTaiKhoan WHERE ThoiDiemKhoaSoID = '{0}' AND TaiKhoanID = '{1}'",
                                                                 dtTableSource.Rows[0]["ThoiDiemKhoaSoID"], dtTableSource.Rows[0]["TaiKhoanID"]);
                        break;
                    case "SoDuTheoDoiTuong":
                        queryDelete = string.Format("DELETE FROM SoDuTheoDoiTuong WHERE ThoiDiemKhoaSoID = '{0}' AND TaiKhoanID = '{1}' AND DoiTuongNghiepVuID = '{2}'",
                                                                 dtTableSource.Rows[0]["ThoiDiemKhoaSoID"], dtTableSource.Rows[0]["TaiKhoanID"], dtTableSource.Rows[0]["DoiTuongNghiepVuID"]);
                        break;
                    case "GhiNo":
                        queryDelete = string.Format("DELETE FROM GhiNo WHERE ButToanID = '{0}' AND TaiKhoanID = '{1}'",
                                                                  dtTableSource.Rows[0]["ButToanID"], dtTableSource.Rows[0]["TaiKhoanID"]);
                        break;
                    case "GhiCo":
                        queryDelete = string.Format("DELETE FROM GhiCo WHERE ButToanID = '{0}' AND TaiKhoanID = '{1}'",
                                                                 dtTableSource.Rows[0]["ButToanID"], dtTableSource.Rows[0]["TaiKhoanID"]);
                        break;
                    case "GiaoDienFormDanhSachChungTu":
                        queryDelete = string.Format("DELETE FROM GiaoDienFormDanhSachChungTu WHERE LoaiChungTuID = '{0}' AND ColumnID = '{1}'",
                                                                  dtTableSource.Rows[0]["LoaiChungTuID"], dtTableSource.Rows[0]["ColumnID"]);
                        break;
                    case "GiaoDienNhapChungTu":
                        queryDelete = string.Format("DELETE FROM GiaoDienNhapChungTu WHERE LoaiChungTuID = '{0}' AND ColumnID = '{1}'",
                                                                   dtTableSource.Rows[0]["LoaiChungTuID"], dtTableSource.Rows[0]["ColumnID"]);
                        break;
                    case "User_Role":
                        queryDelete = string.Format("DELETE FROM User_Role WHERE UserID = '{0}' AND RoleID = '{1}'",
                                                                   dtTableSource.Rows[0]["UserID"], dtTableSource.Rows[0]["RoleID"]);
                        break;
                    case "Role_Function":
                        queryDelete = string.Format("DELETE FROM Role_Function WHERE RoleID = '{0}' AND FunctionID = '{1}'",
                                                                    dtTableSource.Rows[0]["RoleID"], dtTableSource.Rows[0]["FunctionID"]);
                        break;
                    case "ChiTietKhuyenMaiTheoThoiGian":
                        queryDelete = string.Format("DELETE FROM ChiTietKhuyenMaiTheoThoiGian WHERE ChuongTrinhKhuyenMaiID = '{0}' AND VatTuHangHoaID = '{1}'",
                                                                    dtTableSource.Rows[0]["ChuongTrinhKhuyenMaiID"], dtTableSource.Rows[0]["VatTuHangHoaID"]);
                        break;
                    case "ChiTietKhuyenMaiTheoTongTienTichLuy":
                        queryDelete = string.Format("DELETE FROM ChiTietKhuyenMaiTheoTongTienTichLuy WHERE ChuongTrinhKhuyenMaiID = '{0}' AND TongTienTu = {1} AND TongTienDen = {2}",
                                                                 dtTableSource.Rows[0]["ChuongTrinhKhuyenMaiID"], dtTableSource.Rows[0]["TongTienTu"].ToString(), dtTableSource.Rows[0]["TongTienDen"].ToString());
                        break;
                    case "DoiTuongKhuyenMai":
                        queryDelete = string.Format("DELETE FROM DoiTuongKhuyenMai WHERE ChuongTrinhKhuyenMaiID = '{0}' AND DoiTuongNghiepVuID = '{1}'",
                                                                    dtTableSource.Rows[0]["ChuongTrinhKhuyenMaiID"], dtTableSource.Rows[0]["DoiTuongNghiepVuID"]);
                        break;
                    default:
                        break;
                }
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new CustomException(ex.Message);
                }
            }


            if (isTrungTamDenTram)
            {
                //Xóa ở Trạm
                cmd2.CommandText = queryDelete;
                cmd2.ExecuteNonQuery();

                //Insert lại Trung Tâm đến Trạm
                string values = "", listOfColumns = "";
                try
                {
                    if (dtTableSource.Rows.Count > 0)
                    {
                        GetListOfColumnsForInsert(out listOfColumns, out values, cmd2, dtTableSource);

                        queryDelete = string.Format("INSERT INTO {0}({1}) VALUES ({2})", tableName, listOfColumns, values);
                        cmd2.ExecuteNonQuery();

                    }
                    cmd1.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                    cmd1.ExecuteNonQuery();
                }
                catch (SqlException sqlEx)
                {
                    throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                }
                catch (Exception ex)
                {
                    if (ex is CustomException) throw ex;
                    else
                    {
                        throw new CustomException(ex.Message);
                    }
                }
            }
            else
            {
                //Xóa ở Trung Tâm
                cmd1.CommandText = queryDelete;
                cmd1.ExecuteNonQuery();

                //Insert lại Trạm đến Trung Tâm
                string values = "", listOfColumns = "";
                try
                {
                    if (dtTableSource.Rows.Count > 0)
                    {
                        GetListOfColumnsForInsert(out listOfColumns, out values, cmd1, dtTableSource);

                        queryDelete = string.Format("INSERT INTO {0}({1}) VALUES ({2})", tableName, listOfColumns, values);
                        cmd1.ExecuteNonQuery();

                    }
                    cmd2.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                    cmd2.ExecuteNonQuery();
                }
                catch (SqlException sqlEx)
                {
                    throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
                }
                catch (Exception ex)
                {
                    if (ex is CustomException) throw ex;
                    else
                    {
                        throw new CustomException(ex.Message);
                    }
                }
            }
        }

        public void SynData()
        {
            #region Khai báo biến chung
            SqlConnection con1 = new SqlConnection(), con2 = new SqlConnection();
            try
            {
                con1.ConnectionString = ConnectionString1;
                con2.ConnectionString = ConnectionString2;
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    _ErrorMessage = string.Format("Lỗi chuỗi kết nối: {0}", ex.Message);
                    throw new Exception(_ErrorMessage);
                }
            }

            int countRecordsCanDongBoTrungTamDenTram = 0;
            int countRecordsCanDongBoTramDenTrungTam = 0;
            int countRecordsCanDongBo = 0;
            int countRecordsDaDongBoTTDenTram = 0;
            int countRecordsDaDongBoTramDenTT = 0;
            int conChay = 0;

            #endregion

            if (countRecordsCanDongBo >= 0)
            {
                try
                {
                    #region  Test kết nối và khai báo biến setting

                    try
                    {
                        con1.Open();
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Lỗi kết nối đến CSDL Trung tâm");
                        return;
                    }

                    try
                    {
                        con2.Open();
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Lỗi kết nối đến CSDL Trạm");
                        return;
                    }

                    SqlCommand cmd1 = con1.CreateCommand();
                    SqlCommand cmd2 = con2.CreateCommand();
                    SqlDataReader dr = null;

                    string synInfoID = "";
                    string storeID = "";
                    string tableName = "";
                    string tableID = "";
                    string recordID = "";
                    ChangeType changeType = ChangeType.None;
                    ChieuDongBo chieuDongBo = (ChieuDongBo)LocalSettings.HeThong.ChieuDongBo;

                    if (LocalSettings.HeThong.KieuDongBo == KieuDongBo.DongBoToanBo) LoadSyninfoToMemory();
                    else if (LocalSettings.HeThong.KieuDongBo == KieuDongBo.DongBoTheoBlock) LoadSyninfoToMemory(100);

                    countRecordsCanDongBoTrungTamDenTram = _DataTableSynInfo1.Rows.Count;
                    countRecordsCanDongBoTramDenTrungTam = _DataTableSynInfo2.Rows.Count;
                    countRecordsCanDongBo = countRecordsCanDongBoTrungTamDenTram + countRecordsCanDongBoTramDenTrungTam;

                    if (countRecordsCanDongBo == 0)
                    {
                        ShowMessageAutoClose("Không có bản ghi cần đồng bộ!", "Chương trình đồng bộ", 3500, false, false);
                        return;
                    }

                    #endregion

                    if (chieuDongBo == ChieuDongBo.HaiChieu || chieuDongBo == ChieuDongBo.TrungTamDenTram)
                    {
                        #region Dong bo tu CSDL Trung tam ==> CSDL Tram
                        countRecordsDaDongBoTTDenTram = 0;               //Bat dau dem
                        conChay = 0;
                        if (countRecordsCanDongBoTrungTamDenTram <= 0 && chieuDongBo == ChieuDongBo.TrungTamDenTram)
                        {
                            ShowMessageAutoClose("Không có bản ghi cần đồng bộ!", "Chương trình đồng bộ", 3500, false, false);
                            return;
                        }
                        else
                        {
                            while (_DataTableSynInfo1.Rows.Count > conChay)        //Phải dùng while vì khi chuẩn hóa sẽ load lại dữ liệu sẽ không chạy foreach được
                            {
                                DataRow row = _DataTableSynInfo1.Rows[conChay];
                                conChay++;
                                try
                                {
                                    #region Set giá trị

                                    synInfoID = row[0].ToString();
                                    storeID = row[1].ToString();
                                    tableName = row[2].ToString();
                                    tableID = tableName + "ID";
                                    recordID = row[3].ToString();
                                    changeType = (ChangeType)(Convert.ToInt32(row[4].ToString()));

                                    if (con1.State != ConnectionState.Open) con1.Open();
                                    if (con2.State != ConnectionState.Open) con2.Open();
                                    SqlDataAdapter dataAdapterCheck = new SqlDataAdapter();
                                    DataTable dataTableCheck = new DataTable();

                                    #endregion

                                    #region Check xung đột dữ liệu dạng đơn giản
                                    //neu kieu changeType = insert va ID nay da co tren DB tram ==> chuyen thanh Update
                                    if (changeType == ChangeType.Insert)
                                    {
                                        dataTableCheck.Clear();
                                        cmd2.Parameters.Clear();
                                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                        {
                                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                        }
                                        else
                                        {
                                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                        }
                                        dataAdapterCheck.SelectCommand = cmd2;
                                        dataAdapterCheck.Fill(dataTableCheck);
                                        if (dataTableCheck.Rows.Count != 0)
                                        {
                                            changeType = ChangeType.Update;
                                        }
                                    }

                                    //neu kieu changeType = update va ID nay khong co tren DB tram ==> chuyen thanh Insert
                                    if (changeType == ChangeType.Update)
                                    {
                                        dataTableCheck.Clear();
                                        cmd2.Parameters.Clear();
                                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                        {
                                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                        }
                                        else
                                        {
                                            cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                        }
                                        dataAdapterCheck.SelectCommand = cmd2;
                                        dataAdapterCheck.Fill(dataTableCheck);
                                        if (dataTableCheck.Rows.Count == 0)
                                        {
                                            changeType = ChangeType.Insert;
                                        }
                                    }

                                    //lay thong tin tu Db trung tam
                                    if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                    {
                                        cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                    }
                                    else
                                    {
                                        cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                    }
                                    _DataAdapter.SelectCommand = cmd1;
                                    DataTable dtTableSource1 = new DataTable();
                                    dtTableSource1.Clear();
                                    _DataAdapter.Fill(dtTableSource1);
                                    cmd2.Parameters.Clear();
                                    #endregion

                                    #region Synchronize
                                    switch (changeType)
                                    {
                                        case ChangeType.Insert:
                                            string values = "", listOfColumns = "";
                                            try
                                            {
                                                if (dtTableSource1.Rows.Count > 0)
                                                {
                                                    GetListOfColumnsForInsert(out listOfColumns, out values, cmd2, dtTableSource1);

                                                    cmd2.CommandText = string.Format("INSERT INTO [{0}]({1}) VALUES ({2})", tableName, listOfColumns, values);
                                                    cmd2.ExecuteNonQuery();

                                                    //Thử xem đưa vào trong if có hết lỗi không. Nếu vẫn chưa xử lý được mà đã delete thì lần code sau sẽ check exists thì mới cho xóa
                                                    if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                                    {
                                                        cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                                    }
                                                    else
                                                    {
                                                        cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                                    }
                                                    dr = cmd2.ExecuteReader();
                                                    if (dr.Read())
                                                    {
                                                        cmd1.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                                                        cmd1.ExecuteNonQuery();
                                                    }
                                                }

                                                countRecordsDaDongBoTTDenTram++;
                                            }
                                            catch (SqlException sqlEx)
                                            {
                                                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx), cmd1.CommandText, cmd2.CommandText);
                                            }
                                            catch (Exception ex)
                                            {
                                                throw new CustomException(ex.Message, cmd1.CommandText, cmd2.CommandText);
                                            }
                                            finally
                                            {
                                                dr.Close();
                                            }
                                            break;

                                        case ChangeType.Update:
                                            string updateQuery = "";
                                            try
                                            {
                                                if (dtTableSource1.Rows.Count > 0)
                                                {
                                                    GetListOfColumnsForUpdate(out updateQuery, cmd2, dtTableSource1);
                                                    if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                                    {
                                                        cmd2.CommandText = string.Format("UPDATE [{0}] SET {1} WHERE {2} = '{3}'", tableName, updateQuery, tableID, recordID);
                                                    }
                                                    else
                                                    {
                                                        cmd2.CommandText = string.Format("UPDATE [{0}] SET {1} WHERE ID = '{2}'", tableName, updateQuery, recordID);
                                                    }
                                                    cmd2.ExecuteNonQuery();

                                                    //Thử xem đưa vào trong if có hết lỗi không. Nếu vẫn chưa xử lý được mà đã delete thì lần code sau sẽ check exists thì mới cho xóa

                                                    cmd1.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                                                    cmd1.ExecuteNonQuery();
                                                }

                                                countRecordsDaDongBoTTDenTram++;
                                            }
                                            catch (SqlException sqlEx)
                                            {
                                                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx), cmd1.CommandText, cmd2.CommandText);
                                            }
                                            catch (Exception ex)
                                            {
                                                throw new CustomException(ex.Message, cmd1.CommandText, cmd2.CommandText);
                                            }
                                            break;

                                        case ChangeType.Delete:
                                            try
                                            {
                                                if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                                {
                                                    cmd2.CommandText = string.Format("DELETE FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                                }
                                                else
                                                {
                                                    cmd2.CommandText = string.Format("DELETE FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                                }

                                                cmd2.ExecuteNonQuery();
                                                cmd1.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                                                cmd1.ExecuteNonQuery();
                                                countRecordsDaDongBoTTDenTram++;
                                            }
                                            catch (SqlException sqlEx)
                                            {
                                                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx), cmd1.CommandText, cmd2.CommandText);
                                            }
                                            catch (Exception ex)
                                            {
                                                throw new CustomException(ex.Message, cmd1.CommandText, cmd2.CommandText);
                                            }
                                            break;
                                    }
                                    #endregion
                                }
                                catch (CustomException ex)
                                {
                                    _ErrorMessage = ex.ToString();
                                    ShowMessageAutoClose(_ErrorMessage, _CaptionInShowErrorMessage, 5000, true, true, ex.SQL1, ex.SQL2);
                                }
                                catch (Exception ex2)
                                {
                                    _ErrorMessage = ex2.ToString();
                                    ShowMessageAutoClose(_ErrorMessage, _CaptionInShowErrorMessage, 5000, true, true);
                                }
                            }
                        }
                        #endregion
                    }

                    if (chieuDongBo == ChieuDongBo.HaiChieu || chieuDongBo == ChieuDongBo.TramDenTrungTam)
                    {
                        #region Dong bo tu CSDL Tram ==> CSDL Trung tam
                        countRecordsDaDongBoTramDenTT = 0;               //Đếm lại cho Tram -> TT
                        conChay = 0;
                        if (countRecordsCanDongBoTramDenTrungTam == 0 && chieuDongBo == ChieuDongBo.TramDenTrungTam)
                        {
                            ShowMessageAutoClose("Không có bản ghi cần đồng bộ!", "Chương trình đồng bộ", 3500, false, false);
                            return;
                        }
                        else
                        {
                            while (_DataTableSynInfo2.Rows.Count > conChay)   //Phải dùng while vì khi chuẩn hóa sẽ load lại dữ liệu sẽ không chạy foreach được
                            {
                                DataRow row = _DataTableSynInfo2.Rows[conChay];
                                conChay++;
                                try
                                {
                                    #region Set giá trị

                                    synInfoID = row[0].ToString();
                                    storeID = row[1].ToString();
                                    tableName = row[2].ToString();
                                    tableID = tableName + "ID";
                                    recordID = row[3].ToString();
                                    changeType = (ChangeType)(Convert.ToInt32(row[4].ToString()));

                                    if (con1.State != ConnectionState.Open) con1.Open();
                                    if (con2.State != ConnectionState.Open) con2.Open();
                                    SqlDataAdapter dataAdapterCheck = new SqlDataAdapter();
                                    DataTable dataTableCheck = new DataTable();

                                    #endregion

                                    #region Check xung đột dữ liệu dạng đơn giản
                                    //neu kieu changeType = insert va ID nay da co tren DB tram ==> chuyen thanh Update
                                    if (changeType == ChangeType.Insert)
                                    {
                                        cmd1.Parameters.Clear();
                                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                        {
                                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                        }
                                        else
                                        {
                                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                        }
                                        dataAdapterCheck.SelectCommand = cmd1;
                                        dataAdapterCheck.Fill(dataTableCheck);
                                        if (dataTableCheck.Rows.Count != 0)
                                        {
                                            changeType = ChangeType.Update;
                                        }
                                    }

                                    //neu kieu changeType = update va ID nay khong co tren DB tram ==> chuyen thanh Insert
                                    if (changeType == ChangeType.Update)
                                    {
                                        cmd1.Parameters.Clear();
                                        if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                        {
                                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                        }
                                        else
                                        {
                                            cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                        }

                                        dataAdapterCheck.SelectCommand = cmd1;
                                        dataAdapterCheck.Fill(dataTableCheck);
                                        if (dataTableCheck.Rows.Count == 0)
                                        {
                                            changeType = ChangeType.Insert;
                                        }
                                    }

                                    //lay thong tin tu Db Tram
                                    if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                    {
                                        cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                    }
                                    else
                                    {
                                        cmd2.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                    }
                                    _DataAdapter.SelectCommand = cmd2;
                                    DataTable dtTableSource2 = new DataTable();
                                    dtTableSource2.Clear();
                                    _DataAdapter.Fill(dtTableSource2);
                                    cmd1.Parameters.Clear();

                                    #endregion

                                    #region Synchronize

                                    switch (changeType)
                                    {
                                        case ChangeType.Insert:
                                            string values = "", listOfColumns = "";
                                            try
                                            {
                                                if (dtTableSource2.Rows.Count > 0)
                                                {
                                                    GetListOfColumnsForInsert(out listOfColumns, out values, cmd1, dtTableSource2);
                                                    cmd1.CommandText = string.Format("INSERT INTO [{0}]({1}) VALUES ({2})", tableName, listOfColumns, values);
                                                    cmd1.ExecuteNonQuery();

                                                    if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                                    {
                                                        cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                                    }
                                                    else
                                                    {
                                                        cmd1.CommandText = string.Format("SELECT * FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                                    }
                                                    dr = cmd2.ExecuteReader();
                                                    if (dr.Read())
                                                    {
                                                        cmd2.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                                                        cmd2.ExecuteNonQuery();
                                                    }
                                                }

                                                countRecordsDaDongBoTramDenTT++;
                                            }
                                            catch (SqlException sqlEx)
                                            {
                                                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx), cmd1.CommandText, cmd2.CommandText);
                                            }
                                            catch (Exception ex)
                                            {
                                                throw new CustomException(ex.Message, cmd1.CommandText, cmd2.CommandText);
                                            }
                                            finally
                                            {
                                                dr.Close();
                                            }
                                            break;

                                        case ChangeType.Update:
                                            string updateQuery = "";
                                            cmd1.Parameters.Clear();
                                            try
                                            {
                                                if (dtTableSource2.Rows.Count > 0)
                                                {
                                                    GetListOfColumnsForUpdate(out updateQuery, cmd1, dtTableSource2);
                                                    if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                                    {
                                                        cmd1.CommandText = string.Format("UPDATE [{0}] SET {1} WHERE {2} = '{3}'", tableName, updateQuery, tableID, recordID);
                                                    }
                                                    else
                                                    {
                                                        cmd1.CommandText = string.Format("UPDATE [{0}] SET {1} WHERE ID = '{2}'", tableName, updateQuery, recordID);
                                                    }
                                                    cmd1.ExecuteNonQuery();

                                                    cmd2.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                                                    cmd2.ExecuteNonQuery();
                                                }

                                                countRecordsDaDongBoTramDenTT++;
                                            }
                                            catch (SqlException sqlEx)
                                            {
                                                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx), cmd1.CommandText, cmd2.CommandText);
                                            }
                                            catch (Exception ex)
                                            {
                                                throw new CustomException(ex.Message, cmd1.CommandText, cmd2.CommandText);
                                            }
                                            break;

                                        case ChangeType.Delete:
                                            try
                                            {
                                                if (tableName == "ChungTu" || tableName == "KhoanMucChungTu")
                                                {
                                                    cmd1.CommandText = string.Format("DELETE FROM [{0}] WHERE {1} = '{2}'", tableName, tableID, recordID);
                                                }
                                                else
                                                {
                                                    cmd1.CommandText = string.Format("DELETE FROM [{0}] WHERE ID = '{1}'", tableName, recordID);
                                                }
                                                cmd1.ExecuteNonQuery();

                                                cmd2.CommandText = string.Format("DELETE FROM SynInfo WHERE RecordID = '{0}' AND StoreID = {1}", recordID, storeID);
                                                cmd2.ExecuteNonQuery();
                                                countRecordsDaDongBoTramDenTT++;
                                            }
                                            catch (SqlException sqlEx)
                                            {
                                                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx), cmd1.CommandText, cmd2.CommandText);
                                            }
                                            catch (Exception ex)
                                            {
                                                throw new CustomException(ex.Message, cmd1.CommandText, cmd2.CommandText);
                                            }
                                            break;
                                    }
                                    #endregion
                                }
                                catch (CustomException ex)
                                {
                                    _ErrorMessage = ex.ToString();
                                    ShowMessageAutoClose(_ErrorMessage, _CaptionInShowErrorMessage, 5000, true, true, ex.SQL1, ex.SQL2);
                                }
                                catch (Exception ex2)
                                {
                                    _ErrorMessage = ex2.ToString();
                                    ShowMessageAutoClose(_ErrorMessage, _CaptionInShowErrorMessage, 5000, true, true);
                                }
                            }
                        }
                        #endregion
                    }

                    #region Hiển thị thông báo và hậu đồng bộ

                    LocalSettings.HeThong.LastUpdate = DateTime.Now;
                    //FrmProgressBar.FinishShowProgress();

                    int countTotalDaDongBo = countRecordsDaDongBoTTDenTram + countRecordsDaDongBoTramDenTT;
                    if ((countRecordsCanDongBo - countRecordsDaDongBoTTDenTram - countRecordsDaDongBoTramDenTT) == 0 && (countRecordsCanDongBo != 0))
                    {
                        _ErrorMessage = string.Format("Đã đồng bộ xong!\nĐược " + countTotalDaDongBo + " bản ghi.");
                        ShowMessageAutoClose(_ErrorMessage, "Chương trình đồng bộ", 4000, true, false);
                    }
                    else if (countRecordsCanDongBo != 0)
                    {
                        _ErrorMessage = string.Format("Chỉ đồng bộ được : " + countTotalDaDongBo + " / " + countRecordsCanDongBo + " bản ghi.");
                        ShowMessageAutoClose(_ErrorMessage, "Chương trình đồng bộ", 4000, true, true);
                    }
                    if (LocalSettings.HeThong.KieuDongBo == KieuDongBo.DongBoTheoBlock) SynData();  //nếu đồng bộ theo block thì phải liên tục check

                    #endregion
                }
                catch (CustomException ex)
                {
                    _ErrorMessage = ex.ToString();
                    ShowMessageAutoClose(_ErrorMessage, _CaptionInShowErrorMessage, 5000, true, true, ex.SQL1, ex.SQL2);
                }
                catch (Exception ex2)
                {
                    _ErrorMessage = ex2.ToString();
                    ShowMessageAutoClose(_ErrorMessage, _CaptionInShowErrorMessage, 5000, true, true);
                }
                finally
                {
                    _DataTableSynInfo1.Clear();
                    _DataTableSynInfo2.Clear();
                    con1.Close();
                    con2.Close();
                }
            }
        }

        private bool ValidateStoreNameInDB(string connectionString, bool isTrungTam, string storeName)
        {
            using (SqlConnection con = new SqlConnection())
            {
                con.ConnectionString = connectionString;
                DataTable listStoreName = new DataTable();
                SqlDataAdapter da = new SqlDataAdapter();
                try
                {
                    con.Open();
                    SqlCommand cmd = con.CreateCommand();
                    try
                    {
                        cmd.CommandText = string.Format("SELECT * FROM Store WHERE Name = N'{0}'", storeName);
                        da.SelectCommand = cmd;
                        DataTable dvStore = new DataTable();
                        da.Fill(dvStore);

                        if (dvStore.Rows.Count <= 0 && LocalSettings.HeThong.DB_Name != "" && LocalSettings.HeThong.DB_Name2 != "")
                        {
                            if (isTrungTam)
                            {
                                throw new Exception("Lỗi CSDL Trung tâm.\nThông tin cửa hàng không có trong CSDL Trung tâm.\nBạn cần nhập đúng tên cửa hàng.");
                            }
                            else
                            {
                                throw new Exception("Lỗi CSDL Trạm.\nThông tin cửa hàng không có trong CSDL Trạm.\nBạn cần nhập đúng tên cửa hàng.");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (con.State == ConnectionState.Open) con.Close();
                }
                return true;
            }
        }      //Lấy tên các CSDL từ 2 Server về

        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {

        }
    }
}
